<template>
  <div class="app-container">
    <el-row :gutter="20" style="height: 100%">
      <!--组织数据-->
      <el-col v-if="!isStatic" :span="4" :xs="24" class="left-container">
        <SectionList ref="sectionList" :lf="lf"></SectionList>
      </el-col>
      <el-col style="height: 100%" :span="span" :xs="24" class="right-container">
        <div v-if="!isStatic" class="top-title">
          <span style="font-weight: bold">{{ form.productName }}({{ form.version }})</span>
          <el-button type="primary" style="margin-right: 10px" @click="reuseProcess">
            引用流程
          </el-button>
        </div>
        <div v-if="!isStatic || !isEmpty" ref="processContainer" id="process-container"></div>
        <el-empty v-if="isStatic && isEmpty" :image-size="200" />
        <!-- 属性面板 -->
        <PropertyPanel v-if="currentData" :nodeId="currentData"></PropertyPanel>
        <!-- 控制面板 -->
        <Control v-if="!isStatic" :lf="lf"></Control>

        <div v-if="!isStatic" class="footer-page-bottom-action">
          <el-button @click="cancel">取 消</el-button>
          <el-button type="primary" v-loading="saveLoading" @click="submitForm">确 定</el-button>
        </div>
      </el-col>
    </el-row>
    <processSelect v-model="showProcess" @change="handleChange"></processSelect>
  </div>
</template>

<script setup name="Design">
import LogicFlow from "@logicflow/core";
import { Menu } from "@logicflow/extension";
import "@logicflow/core/dist/index.css";
import "@logicflow/extension/lib/style/index.css";
import {
  getProcessManage,
  saveProcessRouteInfo,
  updateProcessRouteInfoById,
  getRouteInfo,
} from "@/api/technology/processManage";
import PropertyPanel from "./propertyPanel";
import processSelect from "./components/processSelect";
import { ElMessageBox } from "element-plus";

import { registerSection, registerEnd, registerStart } from "./registerNode";

import Control from "./control";
import SectionList from "./sectionList.vue";

import { useRoute } from "vue-router";
import { nextTick, toRefs, ref, getCurrentInstance, reactive, computed, onMounted } from "vue";
const props = defineProps({
  disabled: {
    type: Boolean,
    default: false,
  },
  isStatic: {
    type: Boolean,
    default: false,
  },
});
const { isStatic } = toRefs(props);
const route = useRoute();
const { proxy } = getCurrentInstance();
const isEmpty = ref(false);
// const { sys_job_group, sys_job_status } = proxy.useDict(
//   "sys_job_group",
//   "sys_job_status"
// );
const defaultNodes = [
  {
    id: "1",
    type: "start",
    x: 300,
    y: 100,
    text: {
      x: 300,
      y: 100,
      value: "开始",
    },
  },
  {
    id: "2",
    type: "end",
    x: 300,
    y: 400,
    text: {
      x: 300,
      y: 400,
      value: "结束",
    },
  },
];
const processId = ref("");
const processContainer = ref("processContainer");
const sectionList = ref("sectionList");
const lf = ref();
const showProcess = ref(false);
const saveLoading = ref(false);
const dataReactive = reactive({
  form: {},
  data: {
    nodes: [...defaultNodes],
    // 边
    edges: [],
  },
  currentData: null,
});

const { form, data, currentData } = toRefs(dataReactive);

const span = computed(() => {
  return isStatic.value ? 24 : 20;
});

/** 修改按钮操作 */
function handleDetail() {
  getProcessManage(processId.value).then((response) => {
    form.value = response.data;
  });
}

function getRouterData() {
  getRouteInfo(processId.value).then((res) => {
    isEmpty.value = !res.data.nodes || res.data.nodes.length === 0;
    if (res.data && res.data.nodes) {
      res.data.nodes.forEach((el) => {
        el.id = el.nodeId;
        el.type = el.nodeType || "";
        el.properties = {
          workProcedureName: el.nodeText,
          workProcedureCode: el.workProcedureCode,
          id: el.workProcedureId,
        };
      });
    }
    if (res.data && res.data.edges) {
      res.data.edges.forEach((el) => {
        el.id = el.lineId;
        if (el.startPoint) {
          el.startPoint = JSON.parse(el.startPoint);
        }
        if (el.endPoint) {
          el.endPoint = JSON.parse(el.endPoint);
        }
        if (el.pointsList) {
          el.pointsList = JSON.parse(el.pointsList);
        }
      });
    }
    initData(res.data);
    if (lf.value) {
      lf.value.clearData();
    }
    nextTick(() => {
      init();
    });
  });
}

function validator(graphData) {
  // 节点数据
  const nodes = [...graphData.nodes];
  // 边数据
  const edges = [...graphData.edges];
  if (!edges.length) return false;
  // 已纳入寻找路线的节点id
  const nodeIds = new Set([]);
  // 已纳入寻找路线的边id
  const edgeIds = new Set([]);
  // 找出开始节点以及开始节点的线
  const startNodeIndex = nodes.findIndex((node) => (node.type = "start"));
  const startEdgeIndex = edges.findIndex((edge) => edge.sourceNodeId == nodes[startNodeIndex].id);
  if (startNodeIndex == -1 || startEdgeIndex == -1) {
    return false;
  }
  edgeIds.add(edges[startEdgeIndex].id);
  nodeIds.add(edges[startEdgeIndex].sourceNodeId);
  nodeIds.add(edges[startEdgeIndex].targetNodeId);

  // 查找关联
  const _nodeids = getConnect([...edges], edges[startEdgeIndex].targetNodeId);
  _nodeids.forEach((id) => {
    nodeIds.add(id);
  });

  // 已在主流程中的节点数量与所有节点数量相等，说明所有节点都在主流程中
  return nodeIds.size == nodes.length;
}

function init() {
  // processContainer.value.getBoundingClientRect();
  // const ele = document.querySelector("#processContainer");
  lf.value = new LogicFlow({
    // 通过选项指定了渲染的容器和需要显示网格
    container: processContainer.value,
    width: processContainer.value.offsetWidth,
    height: processContainer.value.offsetHeight,
    grid: false,
    isSilentMode: isStatic.value,
    background: {
      backgroundColor: "#f7f9ff",
    },
    keyboard: {
      enabled: true,
      shortcuts: [
        {
          keys: ["delete", "backspace"],
          callback: () => {
            // 当前选中节点/线
            const selectElements = lf.value.getSelectElements();
            const allEle = [...selectElements.edges, ...selectElements.nodes];
            // 删除选中的点/线，除开始/结束节点外
            allEle.forEach((e) => {
              if (!["start", "end"].includes(e.type)) {
                lf.value.deleteElement(e.id);
              }
            });
          },
        },
        {
          keys: ["Up", "Down", "Right", "Left"],
          callback: (event) => {
            // 当前选中节点/线
            const selectElements = lf.value.getSelectElements();
            const allEle = [...selectElements.edges, ...selectElements.nodes];

            let param = [];
            switch (event.key) {
              // 左
              case "ArrowLeft":
                param = [-1, 0];
                break;
              // 右
              case "ArrowRight":
                param = [1, 0];
                break;
              // 上
              case "ArrowUp":
                param = [0, -1];
                break;
              // 下
              case "ArrowDown":
                param = [0, 1];
                break;
              default:
                break;
            }

            if (!param.length) {
              return;
            }

            allEle.forEach((e) => {
              console.log("lf.value.graphModel.moveNode", lf.value.graphModel.moveNode);
              lf.value.graphModel.moveNode(e.id, ...param);
            });
          },
        },
      ],
    },
    textEdit: false,
    edgeTextEdit: false,
    adjustEdgeStartAndEnd: true,
    multipleSelectKey: "shift",
    plugins: [Menu],
  });
  setTheme();
  registerNode();
  setMenu();
  lf.value.render(data.value);
  handleEvent();
}

function getConnect(edges, nodeid) {
  let nodeIds = [];
  edges.forEach((edge) => {
    const _edges = edges.filter((ele) => ele.id != edge.id);
    if (edge.sourceNodeId == nodeid) {
      nodeIds.push(edge.targetNodeId);
      nodeIds = nodeIds.concat(getConnect(_edges, edge.targetNodeId));
    } else if (edge.targetNodeId == nodeid) {
      nodeIds.push(edge.sourceNodeId);
      nodeIds = nodeIds.concat(getConnect(_edges, edge.sourceNodeId));
    }
  });
  return nodeIds;
}

// 设置主题
function setTheme() {
  lf.value.setTheme({
    baseNode: {
      fill: "#FFFFFF",
      stroke: "#666666",
      strokeWidth: 2,
    },
    polyline: {
      stroke: "#666666",
      strokeWidth: 2,
    },
  });
}
// 注册节点
function registerNode() {
  registerSection(lf.value);
  registerEnd(lf.value);
  registerStart(lf.value);
}
// 配置右键菜单
function setMenu() {
  lf.value.extension.menu.setMenuConfig({
    edgeMenu: [
      {
        text: "删除",
        callback: (edge) => {
          lf.value.deleteEdge(edge.id);
        },
      },
    ], // 删除默认的边右键菜单
  });
}
// 绑定事件
function handleEvent() {
  lf.value.on("custom:button-click", (model) => {
    console.log(model.properties);
    if (currentData.value && model.properties.id === currentData.value.id) {
      currentData.value = null;
      return;
    }
    currentData.value = model.properties.id;
  });
}
function getGraphData() {
  return lf.value.getGraphData();
}

function initData(newData) {
  const _nodes = newData?.nodes?.length ? newData.nodes : [...defaultNodes];
  const _edges = newData?.nodes?.length && newData?.edges?.length ? newData.edges : [];
  data.value = {
    // 节点
    nodes: _nodes,
    // 边
    edges: _edges,
  };
}
function resize() {
  nextTick(() => {
    if (lf.value && processContainer.value) {
      lf.value.resize(processContainer.value.offsetWidth, processContainer.value.offsetHeight);
    }
  });
}

function reuseProcess() {
  showProcess.value = true;
}

function handleChange(val) {
  ElMessageBox.confirm(
    `<span>确定引用${val.productName}的工艺流程吗？<br/><i style='color:red'>引用后，将覆盖现当前工艺流程。</i></i>`,
    {
      dangerouslyUseHTMLString: true,
    }
  )
    .then(() => {
      getRouteInfo(val.id).then((res) => {
        if (res.data && res.data.nodes) {
          res.data.nodes.map((el) => {
            el.id = el.nodeId;
            el.type = el.nodeType || "";
            el.properties = {
              workProcedureName: el.nodeText,
              id: el.workProcedureId,
            };
          });
        }
        if (res.data && res.data.edges) {
          res.data.edges.map((el) => {
            el.id = el.lineId;
          });
        }

        initData(res.data);
        if (lf.value) {
          lf.value.clearData();
        }
        nextTick(() => {
          init();
        });
      });
    })
    .catch(() => {});
}

function cancel() {
  const obj = { path: "/processManage/detail/" + processId.value };
  proxy.$tab.closeOpenPage(obj);
}

function dealTreeData(data) {
  let workProcedureIds = [];
  let serialNo = [];
  let workProcedureCode = [];
  data.forEach((el, index) => {
    if (el.properties.workProcedureCode) {
      workProcedureIds.push(el.properties.id);
      workProcedureCode.push(el.properties.workProcedureCode);
      serialNo.push(index);
    }
  });
  return {
    workProcedureIds,
    serialNo,
    workProcedureCode,
  };
}

function submitForm() {
  saveLoading.value = true;
  const graphData = getGraphData();

  // 校验
  const flag = validator(graphData);
  if (!flag) {
    // 校验不通过
    proxy.$modal.msgError("路线不完整，请查看");
    saveLoading.value = false;
    return;
  }
  console.log("graphData", graphData);
  const procedures = dealTreeData(graphData.nodes);
  if (!procedures || procedures.workProcedureCode.length == 0) {
    proxy.$modal.msgError("至少添加一个工序");
    saveLoading.value = false;
    return;
  }
  const param = {
    procedures: procedures,
    processManageId: processId.value,
    nodes: graphData.nodes.map((ele, index) => ({
      id: ele.id,
      workProcedureCode: ele.properties.workProcedureCode || "",
      workProcedureId: ele.properties.id,
      serialNo: index,
      type: ele.type,
      x: ele.x,
      y: ele.y,
      text: ele.properties.workProcedureName,
    })),
    edges: graphData.edges.map((ele) => ({
      id: ele.id,
      sourceNodeId: ele.sourceNodeId,
      targetNodeId: ele.targetNodeId,
      startPoint: JSON.stringify(ele.startPoint),
      endPoint: JSON.stringify(ele.endPoint),
      pointsList: JSON.stringify(ele.pointsList),
      type: "polyline",
      text: "",
    })),
  };
  console.log("param", param);
  if (isEmpty.value) {
    saveProcessRouteInfo(param)
      .then((res) => {
        saveLoading.value = false;
        if (res.code == 200) {
          proxy.$modal.msgSuccess("保存成功！");
          cancel();
        }
      })
      .catch(() => {
        saveLoading.value = false;
      });
  } else {
    updateProcessRouteInfoById(param)
      .then((res) => {
        saveLoading.value = false;
        if (res.code == 200) {
          proxy.$modal.msgSuccess("保存成功！");
          cancel();
        }
      })
      .catch(() => {
        saveLoading.value = false;
      });
  }
}

onMounted(() => {
  if (route.params && route.params.processId) {
    processId.value = route.params.processId;
    if (!isStatic.value) handleDetail();
    getRouterData();
  }
  nextTick(() => {
    init();
  });
});
window.addEventListener("resize", resize);
</script>
<style lang="scss" scoped>
.hasTagsView .app-main .app-container {
  position: relative;
  min-width: 600px;
  height: calc(100vh - 84px);
  min-height: 400px;
}

.app-main .app-container {
  position: relative;
  width: 100%;
  min-width: 600px;
  height: calc(100vh - 50px);
  min-height: 400px;
  overflow: hidden;
}

#process-container {
  width: 100%;
  height: calc(100% - 78px);
}

.footer-page-bottom-action {
  width: 100%;
  height: 56px;
  line-height: 56px;
  text-align: center;
  background: #fff;
  border-radius: 0 0 8px 8px;
  box-shadow: 0 -2px 6px 0 rgb(0 0 0 / 5%);
}

.top-title {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
}
</style>
